﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.Customization;
using Autodesk.AutoCAD.Runtime;

namespace AutoCADDotNetLibrary
{
    /// <summary>
    /// 下拉菜单项特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class PopMenuItemAttribute : Attribute
    {
        /// <summary>
        /// 下拉菜单项特性
        /// </summary>
        /// <param name="index">顺序</param>
        public PopMenuItemAttribute(int index)
        {
            Index = index;
        }

        /// <summary>
        /// 顺序
        /// </summary>
        public int Index { get; private set; }

        /// <summary>
        /// 名称（null时，默认名称为宏的名称）
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 元素Id（AutoCAD会自动生成）
        /// </summary>
        public string UID { get; set; }

        /// <summary>
        /// 是否后面添加分隔符
        /// </summary>
        public bool IsAddSeparatorAfter { get; set; } = false;

        /// <summary>
        /// 特性转换
        /// </summary>
        /// <param name="menuMacro">宏</param>
        /// <param name="parent"></param>
        /// <returns></returns>
        internal PopMenuItem GetPopMenuItem(MenuMacro menuMacro, PopMenu parent)
        {
            if (string.IsNullOrEmpty(Name))
            {
                Name = menuMacro.macro.Name;//默认名称为宏的名称
            }
            PopMenuItem r = new PopMenuItem(menuMacro, Name, parent, -1)
            {
                ElementID = UID
            };
            if (IsAddSeparatorAfter)
                new PopMenuItem(parent);

            return r;
        }
    }

    /// <summary>
    /// 下拉菜单项特性
    /// </summary>
    public static class PopMenuItemAtt
    {
        /// <summary>
        /// 添加类型中的具有<see cref="PopMenuItemAttribute"/>和<see cref="CommandMethodAttribute"/>的方法到下拉菜单项中
        /// </summary>
        /// <param name="menu">下拉菜单</param>
        /// <param name="menuMacros">key=命令,value=宏，<see cref="MenuMacroAtt.AddAssemblyMenuMacro(MacroGroup, System.Reflection.Assembly, string, int)"/>的返回值</param>
        /// <param name="type">类型（具有<see cref="PopMenuItemAttribute"/>和<see cref="CommandMethodAttribute"/>的方法）</param>
        /// <returns></returns>
        public static PopMenuItem[] AddPopMenuItem(this PopMenu menu, Dictionary<string, MenuMacro> menuMacros, Type type)
        {
            PopMenuItem[] list = type.GetMethods().Select(x => new
            {
                PopMenuItem = x.GetCustomAttributes(typeof(PopMenuItemAttribute), false).OfType<PopMenuItemAttribute>(),
                Command = x.GetCustomAttributes(typeof(CommandMethodAttribute), false).OfType<CommandMethodAttribute>()
            }).Where(x => x.PopMenuItem.Count() != 0 && x.Command.Count() != 0)
               .Select(x => new
               {
                   Command = x.Command.First().GlobalName,
                   PopMenuItem = x.PopMenuItem.First(),
               }).OrderBy(x => x.PopMenuItem.Index).Select(x =>
               {
                   if (!menuMacros.ContainsKey(x.Command))
                       return null;

                   return x.PopMenuItem.GetPopMenuItem(menuMacros[x.Command], menu);
               }).Where(x => x != null).ToArray();

            return list;
        }

        /// <summary>
        /// 添加类型中的具有<see cref="PopMenuItemAttribute"/>和<see cref="CommandMethodAttribute"/>的方法到二级菜单中
        /// </summary>
        /// <param name="parent">下拉菜单</param>
        /// <param name="name">名称</param>
        /// <param name="menuMacros">key=命令,value=宏，<see cref="MenuMacroAtt.AddAssemblyMenuMacro(MacroGroup, System.Reflection.Assembly, string, int)"/>的返回值</param>
        /// <param name="type">类型（具有<see cref="PopMenuItemAttribute"/>和<see cref="CommandMethodAttribute"/>的方法）</param>
        /// <returns></returns>
        public static PopMenu AddPopMenu(this PopMenu parent, string name, Dictionary<string, MenuMacro> menuMacros, Type type)
        {
            PopMenu pm = new PopMenu(name, null, "", parent.CustomizationSection.MenuGroup);
            pm.AddPopMenuItem(menuMacros, type);
            PopMenuRef menuRef = new PopMenuRef(pm, parent, -1);
            return pm;
        }
    }
}